package com.we823.project.controller.product;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.we823.project.common.utils.CodeGenerate;
import com.we823.project.common.web.StockUtil;
import com.we823.project.common.web.status.PermissionStatus;
import com.we823.project.common.web.status.PlanStatus;
import com.we823.project.common.web.status.TaskStatus;
import com.we823.project.controller.AbstractBaseController;
import com.we823.project.core.web.WebConstants;
import com.we823.project.model.StationModel;
import com.we823.project.model.UserModel;
import com.we823.project.model.product.PlanDetailModel;
import com.we823.project.model.product.PlanModel;
import com.we823.project.model.product.ProductTaskModel;
import com.we823.project.model.repo.MaterialModel;
import com.we823.project.model.repo.MaterialStockInModel;
import com.we823.project.model.repo.StockInTaskModel;
import com.we823.project.repository.service.StationService;
import com.we823.project.repository.service.UserService;
import com.we823.project.repository.service.product.PlanDetailService;
import com.we823.project.repository.service.product.PlanService;
import com.we823.project.repository.service.product.ProductTaskService;
import com.we823.project.repository.service.repo.MaterialService;
import com.we823.project.repository.service.repo.MaterialStockInService;
import com.we823.project.repository.service.repo.MaterialStockService;
import com.we823.project.repository.service.repo.StockInTaskService;
import com.we823.utils.web.RequestUtil;

@Controller
@RequestMapping(WebConstants.PRODUCT_PLAN)
public class PlanController extends AbstractBaseController<PlanModel> {

	private String baseUrl = WebConstants.PRODUCT_PLAN_TEMPLATE;
	
	private Logger logger = org.slf4j.LoggerFactory.getLogger(PlanController.class);
	
	private PlanService planService;
	
	private @Resource StationService stationService;
	private @Resource PlanDetailService planDetailService;
	private @Resource MaterialService materialService;
	private @Resource ProductTaskService productTaskService;
	private @Resource UserService userService;
	private @Resource MaterialStockInService materialStockInService;
	private @Resource StockInTaskService stockInTaskService; 
	private @Resource MaterialStockService materialStockService;
	
	@Autowired
	public PlanController(PlanService planService) {
		super(planService);
		this.planService = planService;
		super.baseUrl = baseUrl;
		super.entityName = "plan";
		setResourceIdentity("task:plan");
	}

	@Override
	public Page<PlanModel> getData(PageRequest pageRequest, HttpServletRequest request, Model model, boolean pageable) {
		Page<PlanModel> planPage = null;
		if(pageable){
			if(pageRequest!=null){
				planPage = planService.findAll(pageRequest);
			}
		}else{
			Sort sort = getSort(request);
			planPage = new PageImpl<>(planService.findAll(sort));
		}
		fillMaterialInfo(planPage);
		return planPage;
	}

	

	@Override
	protected Sort getSort(HttpServletRequest request) {
		boolean _searchable = RequestUtil.getValueByParam(request, "_search",false);
		if(!_searchable){
			return new Sort(Direction.DESC,"addtime");
		}
		return super.getSort(request);
	}
	
	@Override
	public String preAdd(HttpServletRequest request, Model model) {
		String resultUrl = super.preAdd(request, model);
		Long maxId = planService.getMaxId();
		model.addAttribute("code","STEP-C-SSL-"+maxId);
		
		List<StationModel> stationModels = stationService.findAll();
		model.addAttribute("stations",stationModels);
		
		Date date = new Date();
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
		String startDate = simpleDateFormat.format(date);
		String endDate = simpleDateFormat.format(DateUtils.addDays(date, 2));
		
		model.addAttribute("startDate",startDate);
		model.addAttribute("endDate",endDate);
		
		logger.debug(endDate);
		return resultUrl;
	}

	@Override
	public String add(HttpServletRequest request, PlanModel entity, Model model, BindingResult bindingResult,RedirectAttributes redirectAttributes) {
		check(PermissionStatus.CREATE);
		if(entity!=null){
			entity.setAddtime(new Date());
			entity.setStatus(PlanStatus.NoFinish);
			
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyMMdd");
			String name = "["+entity.getMaterialCode()+"]"+simpleDateFormat.format(entity.getStartDate())+"生产计划";
			entity.setName(name);
			
			UserModel userModel = (UserModel) request.getSession().getAttribute(WebConstants.CURRENT_USER);
			if(userModel!=null) {
				entity.setInputer(userModel.getRealname());
				entity.setUser(userModel);
				entity.setUsername(userModel.getUsername());
			}
		}
		
		entity = planService.save(entity);
		Integer planId = 0;
		if(entity!=null){
			planId = entity.getId();
		}
		Integer currentId = RequestUtil.getValueByParam(request, "current_id", 0);
		if(planId>0 && currentId>0){
			String dateFormat = "yyyy-MM-dd";
			String planCode = entity.getCode();
			for(int index=0;index<currentId;index++){
				Date startDate = RequestUtil.getDateValueByParam(request, "startDate_"+index,dateFormat);
				String modelString = RequestUtil.getValueByParam(request, "materialModel_"+index);
				String materialCode = RequestUtil.getValueByParam(request, "materialCode_"+index);
				String unit = RequestUtil.getValueByParam(request, "unit_"+index);
				
				float needTotal = RequestUtil.getValueByParam(request, "needTotal_"+index, 0f);
				String materialDesc = RequestUtil.getValueByParam(request, "materialDesc_"+index);
				Integer stationId = RequestUtil.getValueByParam(request, "station_"+index, 0);
				Date finishDate = RequestUtil.getDateValueByParam(request, "finishDate_"+index,dateFormat);
				String memo = RequestUtil.getValueByParam(request, "memo_"+index);
				
				int deep = RequestUtil.getValueByParam(request, "deep_"+index,1);
				int orderid = RequestUtil.getValueByParam(request, "orderid_"+index, 1);
				String process = RequestUtil.getValueByParam(request, "process_"+index);
				
				String nextProcess = RequestUtil.getValueByParam(request, "nextProcess_"+index);
				String preProcess = RequestUtil.getValueByParam(request, "preProcess_"+index);
				String destCode = RequestUtil.getValueByParam(request, "destCode_"+index);
				String destModel = RequestUtil.getValueByParam(request, "destModel_"+index);
				
				PlanDetailModel planDetailModel = new PlanDetailModel();
				planDetailModel.setPlanId(planId);
				planDetailModel.setPlanCode(planCode);
				planDetailModel.setCreateDate(startDate);
				planDetailModel.setMaterialCode(materialCode);
				planDetailModel.setMaterialModel(modelString);
				planDetailModel.setMaterialDesc(materialDesc);
				planDetailModel.setNeedTotal(needTotal);
				planDetailModel.setUnit(unit);
				planDetailModel.setStationId(stationId);
				planDetailModel.setFinishDate(finishDate);
				planDetailModel.setMemo(memo);
				planDetailModel.setAddtime(new Date());
				
				planDetailModel.setType(entity.getType());
				planDetailModel.setDeep(deep);
				planDetailModel.setOrderid(orderid);
				planDetailModel.setProcess(process);
				
				planDetailModel.setNextProcess(nextProcess);
				planDetailModel.setPreProcess(preProcess);
				
				planDetailModel.setDestCode(destCode);
				planDetailModel.setDestModel(destModel);
				
				planDetailModel.setMemo(memo);
				
				if(stationId>0){
					planDetailModel.setStatus(TaskStatus.NoConfirm);
				}else{
					planDetailModel.setStatus(TaskStatus.NoAssign);
				}
				
				planDetailService.save(planDetailModel);
			}
		}
		return listUrl;
	}
	@RequestMapping("getOne")
	@ResponseBody
	public Model getOne(HttpServletRequest request,Model model) {
		int id = RequestUtil.getValueByParam(request, "id", 0);
		boolean hasError = false;
		String message = "";
		if (id>0) {
			PlanModel planModel = planService.findOne(id);
			if (planModel!=null) {
				try {
					fillDetailInfo(planModel);
					
					model.addAttribute("plan",planModel);
				} catch (Exception e) {
					hasError=true;
					message = e.getMessage();
				}
				
			}
		}else {
			hasError = true;
			message = "参数不正确";
		}
		
		model.addAttribute("hasError",hasError);
		model.addAttribute("message",message);
		return model;
	}
	
	/**
	 * 提交入库
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping("submitStockIn")
	@ResponseBody
	public Model submitStockIn(HttpServletRequest request,Model model) {
		int id = RequestUtil.getValueByParam(request, "planId", 0);
		int taskId = RequestUtil.getValueByParam(request, "taskId", 0);
		Float finalNum = RequestUtil.getFloatValueByParam(request, "finalNum");
		String memo = RequestUtil.getValueByParam(request, "memo");
		
		if (id>0 && taskId>0) {
			MaterialStockInModel materialStockInModel = new MaterialStockInModel();
			materialStockInModel.setCode(CodeGenerate.getMaterialStockInCode());
			
			String materialCode = null;
			
			String checkstatus = "未确认";
			
			PlanModel planModel = planService.findOne(id);
			if (planModel!=null) {
				materialCode = planModel.getMaterialCode();
			}
			
			MaterialModel materialModel = materialService.findByCode(materialCode);
			if (materialModel!=null) {
				materialStockInModel.setMaterialCode(materialCode);
				materialStockInModel.setUnit(materialModel.getUnit());
				materialStockInModel.setTotalNum(finalNum);
				
				UserModel userModel = getUser(request);
				String realname = "未知";
				if (userModel!=null) {
					realname = userModel.getRealname();
					if (StringUtils.isEmpty(realname)) {
						realname = userModel.getUsername();
					}
				}
				materialStockInModel.setInputer(realname);
				
				materialStockInModel.setMemo(memo);
				materialStockInModel.setAddtime(new Date());
				materialStockInModel.setCheckstatus(checkstatus);

                materialStockInService.save(materialStockInModel);
                int stockInId = materialStockInModel.getId();
                if (stockInId>0) {
					StockInTaskModel stockInTaskModel = new StockInTaskModel();
					stockInTaskModel.setAddtime(new Date());
					stockInTaskModel.setStockInId(stockInId);
					stockInTaskModel.setTaskId(taskId);
					stockInTaskService.save(stockInTaskModel);
					
					//调整库存信息
					StockUtil.changeStock(materialStockInModel, materialStockService);
					model.addAttribute("hasError",false);
					
					planModel.setStatus(PlanStatus.Finish);
					planService.update(planModel);
				}else {
					model.addAttribute("hasError",true);
					model.addAttribute("message","入库信息新增异常，请检查网络");
				}
			}
		}else {
			model.addAttribute("hasError",true);
			model.addAttribute("message","计划号或任务单号不正确");
		}
		return model;
	}
	
	private UserModel getUser(HttpServletRequest request) {
		UserModel userModel = (UserModel) request.getSession().getAttribute(WebConstants.CURRENT_USER);
		return userModel;
	}
	/**
	 * 填充最后一道工序信息、物料信息、生产人员信息
	 * @param planModel
	 * @throws Exception 
	 */
	private void fillDetailInfo(PlanModel planModel) throws Exception {
		if (planModel!=null) {
			String materialCode = planModel.getMaterialCode();
			MaterialModel materialModel = materialService.findByCode(materialCode);
			if (materialModel!=null) {
				planModel.setMaterial(materialModel);;
				planModel.setMaterialModel(materialModel.getFullname());
				planModel.setUnit(materialModel.getUnit());
			}
			
			Integer planId = planModel.getId();
			/**
			 * 无 后续工序为最后一道工序
			 */
			List<PlanDetailModel> planDetailModels = planDetailService.findByPlanIdAndNextProcess(planId,"无");
			if (planDetailModels!=null && planDetailModels.size()>0) {
				PlanDetailModel planDetailModel = planDetailModels.get(0);
				if (planDetailModel!=null) {
					ProductTaskModel productTaskModel = productTaskService.findByPlanDetialId(planDetailModel.getId());
					if (productTaskModel!=null) {
						int userId = productTaskModel.getUserId();
						UserModel userModel = userService.findOne(userId);
						if (userModel!=null) {
							if (StringUtils.isEmpty(userModel.getRealname())) {
								planDetailModel.setRealname(userModel.getUsername());
							}else {
							    planDetailModel.setRealname(userModel.getRealname());
							}
						}
						
						int stationId = planDetailModel.getStationId();
						StationModel stationModel = stationService.findOne(stationId);
						if (stationModel!=null) {
							planDetailModel.setStationName(stationModel.getName());
						}
						
						planDetailModel.setFinalNum(productTaskModel.getFinalTotal());
						planDetailModel.setTaskCode(productTaskModel.getCode());
						planDetailModel.setTaskId(productTaskModel.getId());
					}
					
					planModel.setLastPlanDetail(planDetailModel);
				}
			}else {
				throw new Exception("查找计划详情有误，无法申请入库");
			}
		}
		
	}

	private void fillMaterialInfo(Page<PlanModel> planPage) {
		if (planPage!=null) {
			List<PlanModel> planModels = planPage.getContent();
			if (planModels!=null && planModels.size()>0) {
				List<String> materialCodeList = Lists.newArrayList();
				for (PlanModel planModel : planModels) {
					materialCodeList.add(planModel.getMaterialCode());
				}
				
				List<MaterialModel> materialModels = materialService.findByCodeIn(materialCodeList);
				if (materialModels!=null && materialModels.size()>0) {
					Map<String, MaterialModel> map = Maps.newHashMap();
					for (MaterialModel materialModel : materialModels) {
						map.put(materialModel.getCode(), materialModel);
					}
					
					for (PlanModel planModel : planModels) {
						MaterialModel materialModel = map.get(planModel.getMaterialCode());
						if (materialModel!=null) {
							planModel.setMaterialModel(materialModel.getFullname());
							planModel.setUnit(materialModel.getUnit());
						}
					}
				}
			}
		}
		
	}


}
